/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

//package MeshlessShapeFunctions;

import HashMatrix2.HashMatrix2;
import HashMatrix2.LUFactorization;
import MeshlessShapeFunctions.IKernelFunction;
import MeshlessShapeFunctions.JGaussian;
import MeshlessShapeFunctions.Particle;

import java.util.ArrayList;
import java.util.Iterator;

import jmeshless.NewOkCancelDialog;

import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 *
 * @author mark
 */
public class JMeshlessInterpolationFunction1D {

    protected int PolinomialDegree;
    protected double xii;
    protected double rho;
    protected IKernelFunction func;
    protected HashMatrix2 A;
    protected double[] b;
    protected ArrayList<Particle> NodeList;
    


    public JMeshlessInterpolationFunction1D(int PolinomialDegree, double xi, double rho, IKernelFunction func) {
        this.PolinomialDegree = PolinomialDegree;
        this.xii = xi;
        this.rho = rho;
        this.func = func;
    }

    public double getRho() {
        return rho;
    }

    public double getXii() {
        return xii;
    }

    public void setNodeList(ArrayList<Particle> NodeList) {
        this.NodeList = NodeList;
    }

    public ArrayList<Double> getBaseVector(double x, double xi){
        ArrayList<Double> L = new ArrayList<Double>();
        for (int i = 0; i <= this.PolinomialDegree; i++) {
            L.add(Math.pow((xi), i));
        }
        L.add((Math.exp(10*xi)));
        return L;
    }

    public ArrayList<Double> getBaseVectorDerivaty(double x, double xi){
        ArrayList<Double> L = new ArrayList<Double>();
        L.add(0.0);
        for (int i = 1; i <= this.PolinomialDegree; i++) {
            L.add(i * Math.pow((xi), i-1));
        }
        return L;
    }


    public double calculate(double x){
        ArrayList<Double> BaseVector = getBaseVector(x, xii);
        int n = BaseVector.size();
        b = new double[n];
        A = new HashMatrix2(HashMatrix2.ARRAY_TYPE, n);
        for (int i = 0; i < NodeList.size(); i++) {
            Particle particle = NodeList.get(i);
            calculateAlfa(x,particle.getX());
        }

        /*for (int i = 0; i < b.length; i++) {
        for (int j = 0; j < b.length; j++) {
        System.out.print(A.getValue(i, j));
        }
        System.out.println();
        }

        System.out.println("============================================================");*/

        boolean key=false;
        for (int i = 0; i < b.length; i++) {
            b[i] = BaseVector.get(i)*func.evaluate((xii-x)/rho);
            if(b[i]!=0.0){key = true;}
        }

        double returnValue = 0.0;
        if(key){
            LUFactorization lu = new LUFactorization(A);
            double[] res = lu.calculate(b);

            BaseVector = getBaseVector(x, x);
            for (int i = 0; i < b.length; i++) {
                returnValue+=BaseVector.get(i)*res[i];
            }
        }
        return returnValue;
    }


    private void calculateAlfa(double x, double xi){
        ArrayList<Double> BaseVector = getBaseVector(x, xi);
        int n = BaseVector.size();
        for (int i = 0; i < n; i++) {
            double val = BaseVector.get(i)*func.evaluate((xi-x)/rho);
            for (int j = 0; j < n; j++) {
                A.addValue(i, j, val*BaseVector.get(j));
            }
        }
        //for (int i = 0; i < b.length; i++) {
        //    b[i]+= BaseVector.get(i)*func.evaluate((xi-x)/rho)*x*x;
        //}
    }

    public double calculateDiffuseDerivaty(double x){
        ArrayList<Double> BaseVector = getBaseVector(x, xii);
        int n = BaseVector.size();
        b = new double[n];
        A = new HashMatrix2(HashMatrix2.ARRAY_TYPE, n);
        for (int i = 0; i < NodeList.size(); i++) {
            Particle particle = NodeList.get(i);
            calculateAlfa(x,particle.getX());
        }

        boolean key=false;
        for (int i = 0; i < b.length; i++) {
            b[i] = BaseVector.get(i)*func.evaluate((xii-x)/rho);
            if(b[i]!=0.0){key = true;}
        }

        double returnValue = 0.0;
        if(key){
            LUFactorization lu = new LUFactorization(A);
            double[] res = lu.calculate(b);

            BaseVector = getBaseVectorDerivaty(x, x);

            for (int i = 0; i < b.length; i++) {
                returnValue+=BaseVector.get(i)*res[i];
            }
        }
        return returnValue;
    }

    public double calculateDerivaty(double x){
        ArrayList<Double> BaseVector = getBaseVector(x, xii);
        int n = BaseVector.size();
        b = new double[n];
        A = new HashMatrix2(HashMatrix2.ARRAY_TYPE, n);
        for (int i = 0; i < NodeList.size(); i++) {
            Particle particle = NodeList.get(i);
            calculateAlfa(x,particle.getX());
        }

        boolean key=false;
        for (int i = 0; i < b.length; i++) {
            b[i] = BaseVector.get(i)*func.evaluate((xii-x)/rho);
            if(b[i]!=0.0){key = true;}
        }

        double returnValue = 0.0;
        if(key){
            LUFactorization lu = new LUFactorization(A);
            double[] res = lu.calculate(b);

            BaseVector = getBaseVectorDerivaty(x, xii);

            for (int i = 0; i < b.length; i++) {
                returnValue+=BaseVector.get(i)*res[i];
            }
        }
        return returnValue;
    }
    
    
public static void main(String[] args){

        
        double a = 0.0,b=1;
        double x = a;


        int nn = 10;
        ArrayList<Particle> ls1D = new ArrayList<Particle>();
        ArrayList<JMeshlessInterpolationFunction1D> ls = new ArrayList<JMeshlessInterpolationFunction1D>();
        int PolinomDegree = 1;
        double h = (b-a)/(double)nn;
        for (int i = 0; i <=nn; i++) {
            ls1D.add(new Particle(a+h*i, 0, i));
        }
        
      
      
//      ls1D = new ArrayList<Particle>();
//      double rho = 0.0;
//      
//      ls1D.add( new Particle(0.0 , 0,0 ));
//      rho  = 0.1*2.1;
//      ls1D.get(ls1D.size()-1).setRho(rho);
//      ls1D.add( new Particle(0.05 , 0,1 ));
//      rho  = 0.1*2.1;
//      ls1D.get(ls1D.size()-1).setRho(rho);
//      ls1D.add( new Particle(0.1 , 0,2 ));
//      rho  = 0.15*2.1;
//      ls1D.get(ls1D.size()-1).setRho(rho);
//      ls1D.add( new Particle(0.25 , 0,3 ));
//      rho  = 0.25*2.1;
//      ls1D.get(ls1D.size()-1).setRho(rho);
//      ls1D.add( new Particle(0.5 , 0,4 ));
//      rho  = 0.25*2.1;
//      ls1D.get(ls1D.size()-1).setRho(rho);
//      ls1D.add( new Particle(0.75 , 0,5 ));
//      rho  = 0.25*2.1;
//      ls1D.get(ls1D.size()-1).setRho(rho);
//      ls1D.add( new Particle(0.9, 0,6 ));
//      rho  = 0.15*2.1;
//      ls1D.get(ls1D.size()-1).setRho(rho);
//      ls1D.add( new Particle(0.95 , 0,7 ));
//      rho  = 0.1*2.1;
//      ls1D.get(ls1D.size()-1).setRho(rho);
//      ls1D.add( new Particle(1.0 , 0,8 ));
//      rho  = 0.1*2.1;
//      ls1D.get(ls1D.size()-1).setRho(rho);
      
      
      for (int i = 0; i < ls1D.size(); i++) {
    	  Particle particle = ls1D.get(i);
    	  double rho = (1.1+0.5*(i+1))*h;
    	  rho = (2.1 )*h;
    	  particle.setRho(rho);
    	  JMeshlessInterpolationFunction1D f = new JMeshlessInterpolationFunction1D(PolinomDegree, particle.getX(), particle.getRho(), new JGaussian(particle.getRho()));
    	  ls.add(f);
      }

      for (int i = 0; i < ls1D.size(); i++) {
    	  JMeshlessInterpolationFunction1D f = ls.get(i);
    	  f.setNodeList(ls1D);
      }

	
	XYSeriesCollection col = new XYSeriesCollection();
    for (Iterator<JMeshlessInterpolationFunction1D> it = ls.iterator(); it.hasNext();) {
		JMeshlessInterpolationFunction1D jm = (JMeshlessInterpolationFunction1D) it.next();
		double x1 = 0.0;
		 	XYSeries series = new XYSeries("", true, true);
	        while(x1<=1.0001){
	            double tmp1 = jm.calculate(x1);
	            series.add(x1,tmp1);
	            x1+=0.002;
	        }
	        col.addSeries(series);
	}
    NewOkCancelDialog dialog = new NewOkCancelDialog(null, false, col);
    dialog.setLocationRelativeTo(null);
    dialog.setVisible(true);

    }
    

}




/*
package MeshlessShapeFunctions;

import HashMatrix2.HashMatrix2;
import HashMatrix2.LUFactorization;
import java.util.ArrayList;

public class JMeshlessInterpolationFunction1D {

    protected int PolinomialDegree;
    protected double xii;
    protected double rho;
    protected IKernelFunction func;
    protected HashMatrix2 A;
    protected double[] b;
    protected ArrayList<Particle> NodeList;
    protected LUFactorization lu; //TODO можна зробити ЛУ розклад а тоді просто домножувати на константу отриману з калкулейтАльфа() ......
    protected ArrayList<Double> BaseVector;
    protected ArrayList<Double> BaseVectorTMP;



    public JMeshlessInterpolationFunction1D(int PolinomialDegree, double xi, double rho, IKernelFunction func) {
        this.PolinomialDegree = PolinomialDegree;
        this.xii = xi;
        this.rho = rho;
        this.func = func;
    }

    public void setNodeList(ArrayList<Particle> NodeList) {
        this.NodeList = NodeList;
        BaseVector = getBaseVector(xii);
        A = new HashMatrix2(HashMatrix2.ARRAY_TYPE, BaseVector.size());
        for (int i = 0; i < NodeList.size(); i++) {
            Particle particle = NodeList.get(i);
            BaseVectorTMP = getBaseVector(particle.x);
            for (int j = 0; j < BaseVectorTMP.size(); j++) {
                double tmp = BaseVectorTMP.get(j);
                for (int k = 0; k < BaseVectorTMP.size(); k++) {
                    A.addValue(j, k, tmp*BaseVectorTMP.get(k));
                }
            }
        }

    }

    public ArrayList<Double> getBaseVector(double xi){
        ArrayList<Double> L = new ArrayList<Double>();
        for (int i = 0; i <= this.PolinomialDegree; i++) {
            L.add(Math.pow((xi), i));
        }
        return L;
    }

    public ArrayList<Double> getBaseVectorDerivaty(double xi){
        ArrayList<Double> L = new ArrayList<Double>();
        L.add(0.0);
        for (int i = 1; i <= this.PolinomialDegree; i++) {
            L.add(i * Math.pow((xi), i-1));
        }
        return L;
    }


    public double calculate(double x){
        //ArrayList<Double> BaseVector = getBaseVector(xii);
        int n = BaseVector.size();
        b = new double[n];
        HashMatrix2 A2 = new HashMatrix2(HashMatrix2.ARRAY_TYPE, n);
        double tmp = calculateAlfa(x);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                A2.setValue(i, j, tmp);
            }
        }

        boolean key=false;
        for (int i = 0; i < b.length; i++) {
            b[i] = BaseVector.get(i)*func.evaluate((xii-x)/rho);
            if(b[i]!=0.0){key = true;}
        }

        lu = new LUFactorization(A2);

        double returnValue = 0.0;
        if(key){

            double[] res = lu.calculate(b);

        BaseVectorTMP = getBaseVector(x);
            for (int i = 0; i < b.length; i++) {
                returnValue+=BaseVectorTMP.get(i)*res[i];
            }
        }
        return returnValue;
    }


    private double calculateAlfa(double x){
        int n = BaseVector.size();
        double res = 0.0;
        for (int i = 0; i < n; i++) {
            res+=func.evaluate((NodeList.get(i).x-x)/rho);
        }
        return res;
    }

    public double calculateDiffuseDerivaty(double x){
        //ArrayList<Double> BaseVector = getBaseVector(x, xii);
        int n = BaseVector.size();
        b = new double[n];
        HashMatrix2 A2 = new HashMatrix2(HashMatrix2.ARRAY_TYPE, n);
        double tmp = calculateAlfa(x);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                A2.setValue(i, j, tmp);
            }
        }

        boolean key=false;
        for (int i = 0; i < b.length; i++) {
            b[i] = BaseVector.get(i)*func.evaluate((xii-x)/rho);
            if(b[i]!=0.0){key = true;}
        }

        double returnValue = 0.0;
        if(key){
            LUFactorization lu = new LUFactorization(A);
            double[] res = lu.calculate(b);

            BaseVectorTMP = getBaseVectorDerivaty(x);

            for (int i = 0; i < b.length; i++) {
                returnValue+=BaseVectorTMP.get(i)*res[i];
            }
        }
        return returnValue;
    }

    public double calculateDerivaty(double x){
        BaseVector = getBaseVector(xii);
        int n = BaseVector.size();
        b = new double[n];
        A = new HashMatrix2(HashMatrix2.ARRAY_TYPE, n);
        for (int i = 0; i < NodeList.size(); i++) {
            Particle particle = NodeList.get(i);
            calculateAlfa(x);
        }

        boolean key=false;
        for (int i = 0; i < b.length; i++) {
            b[i] = BaseVector.get(i)*func.evaluate((xii-x)/rho);
            if(b[i]!=0.0){key = true;}
        }

        double returnValue = 0.0;
        if(key){
            LUFactorization lu = new LUFactorization(A);
            double[] res = lu.calculate(b);

            BaseVector = getBaseVectorDerivaty(x);

            for (int i = 0; i < b.length; i++) {
                returnValue+=BaseVector.get(i)*res[i];
            }
        }
        return returnValue;
    }

    public double getRho() {
        return rho;
    }

    public double getXii() {
        return xii;
    }

    public FunctionAndDerivaty calculateBoth(double x){
        int n = BaseVector.size();
        b = new double[n];
        HashMatrix2 A2 = new HashMatrix2(HashMatrix2.ARRAY_TYPE, n);
        double tmp = calculateAlfa(x);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                A2.setValue(i, j, tmp);
            }
        }

        boolean key=false;
        for (int i = 0; i < b.length; i++) {
            b[i] = BaseVector.get(i)*func.evaluate((xii-x)/rho);
            if(b[i]!=0.0){key = true;}
        }

        double returnValueDer = 0.0;
        double returnValueFunc = 0.0;
        if(key){
            LUFactorization LU = new LUFactorization(A);
            double[] res = LU.calculate(b);

            BaseVectorTMP = getBaseVectorDerivaty(x);

            for (int i = 0; i < b.length; i++) {
                returnValueDer+=BaseVectorTMP.get(i)*res[i];
            }

            BaseVectorTMP = getBaseVector(x);

            for (int i = 0; i < b.length; i++) {
                returnValueFunc+=BaseVectorTMP.get(i)*res[i];
            }
        }
        return new FunctionAndDerivaty(returnValueFunc, returnValueDer);
    }

}
*/